#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sched.h>
#include <stdio.h>
#include <stdlib.h>        
#include <errno.h>
#include <string.h>

#define OPEN_CALL 0
#define CLOSE_CALL 1
#define WRITE_CALL 2
#define LSEEK_CALL 3
#define CLONE_CALL 4
#define ALL -1

#define CANVI_PROCES 0
#define CANVI_SYSCALL 1
#define RESET_VALORS 2
#define RESET_VALORS_ALL 3
#define ACTIVAR_SYSCALL 4
#define DESACTIVAR_SYSCALL 5

struct t_info {
    int num_entrades;
    int num_sortides_ok;
    int num_sortides_error;
    unsigned long long durada_total;
};

void salir(void){
	exit(0);
}

int main() {
	char c[64*1024];//64Kb para la pila del clone
	int fd_displayer,fd1,fd_write,pid,res;
	struct t_info stats;
	printf("\nTESTS PARA LAS LLAMADAS A SISTEMA DEL MODULO WATCHER\nLlamadas para probar la recuperación de las estadísitcas a través del dispositivo\n\n");
	printf("Pulsa ENTER para iniciar los tests.");
	fflush(stdout);
	read(0, NULL, 1);

	pid = getpid();
	fd_write = open("fileTOwrite", O_RDWR | O_CREAT, 0777);
	fd_displayer = open("/dev/displayer", O_RDONLY, 0777);
	if(fd_displayer < 0){
		printf("ERROR: No se puede abrir el dispositivo\n");
		exit(0);
	}
	printf("Dispostivo abierto correctamente y reseteamos los valores\n");

	
	res = ioctl(fd_displayer, RESET_VALORS_ALL, 0);
	printf("Selecciona la operacion que quieres realizar: \n [open] | [close] | [write] | [lseek] | [clone] | [salir] \n");
	gets(c);

	while(strcmp(c,"salir") != 0) {
		if (strcmp(c,"open") == 0 || strcmp(c,"close") == 0) {
			printf("\nRealizando un open y un close...\n");
			fd1 = open("newfile", O_RDWR | O_CREAT, 0777);
			if(fd1 < 0) {
				printf("ERROR: No se puede crear el fichero.\n\n");
			        exit(-1);
			}
			res = close(fd1);
			if (strcmp(c,"open") == 0 ){
				res = ioctl(fd_displayer, CANVI_SYSCALL, OPEN_CALL);
				read(fd_displayer, &stats, sizeof(struct t_info));
				printf("OPEN:\n Número entrades: %d \n Número salidas ok: %d \n Número salidas error:%d\n Durada total: %lld \n\n", stats.num_entrades ,stats.num_sortides_ok, stats.num_sortides_error, stats.durada_total);
			}
			else{
				res = ioctl(fd_displayer, CANVI_SYSCALL, CLOSE_CALL);
				read(fd_displayer, &stats, sizeof(struct t_info));
				printf("CLOSE:\n Número entrades: %d \n Número salidas ok: %d \n Número salidas error:%d\n Durada total: %lld \n\n", stats.num_entrades ,stats.num_sortides_ok, stats.num_sortides_error, stats.durada_total);
			}

		}

		if (strcmp(c,"write") == 0) {
			printf("\nRealizando un write... (hay que tener en cuenta que hay más writes intermedios,1 por cada línea escrita por consola)\n");
			res = write(fd_write,"pon nos un 10!",14);
			res = ioctl(fd_displayer, CANVI_SYSCALL, WRITE_CALL);
			read(fd_displayer, &stats, sizeof(struct t_info));
			printf("WRITE:\n Número entrades: %d \n Número salidas ok: %d \n Número salidas error:%d\n Durada total: %lld \n\n", stats.num_entrades ,stats.num_sortides_ok, stats.num_sortides_error, stats.durada_total);

		}

		if(strcmp(c,"lseek") == 0) {
			printf("\nRealizando un lseek...\n");
			res = lseek(fd_write,5,SEEK_CUR);
			res = ioctl(fd_displayer, CANVI_SYSCALL, LSEEK_CALL);
			read(fd_displayer, &stats, sizeof(struct t_info));
			printf("LSEEK:\n Número entrades: %d \n Número salidas ok: %d \n Número salidas error:%d\n Durada total: %lld \n\n", stats.num_entrades ,stats.num_sortides_ok, stats.num_sortides_error, stats.durada_total);
		}

/*		if(strcmp(c,"clone") == 0) {
			printf("\nRealizando un clone...\n");
			res = clone((void*)&salir, (char*)&c,0, 0);
			if(res == -1){
				printf("ERROR: clone(), %d\n",errno);
			}
			res = waitpid(res,&res2,0);
			if(res == -1){
				printf("ERROR: waitpid(), %d\n",errno);
			}
			res = ioctl(fd_displayer, CANVI_SYSCALL, CLONE_CALL);
			read(fd_displayer, &stats, sizeof(struct t_info));
			printf("CLONE:\n Número entrades: %d \n Número salidas ok: %d \n Número salidas error:%d\n Durada total: %lld \n\n", stats.num_entrades ,stats.num_sortides_ok, stats.num_sortides_error, stats.durada_total);
		}
*/
		printf("[open] | [close] | [write] | [lseek] | [clone] | [salir] \n");
		gets(c);
	}
	close(fd_write);
	//eliminar "fileTOwrite"
	unlink("fileTOwrite");
	
	exit(0);
}

